package com.itheima.reggie.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.reggie.dto.resp.R;
import com.itheima.reggie.pojo.*;
import com.itheima.reggie.dto.req.DishDto;
import com.itheima.reggie.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/dish")
public class DishController {

    @Autowired
    private DishService dishService;

    @Autowired
    private DishFlavorService dishFlavorService;
    @Autowired
    private CategoryService categoryService;

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 分页查询
     * 请求url地址：/dish/page ?page=1&pageSize=10&name=白菜
     * 请求方式：GET
     * 请求参数：?page=1&pageSize=10&name=白菜
     *
     * @param page
     * @param pageSize
     * @param name
     * @return
     */
    @GetMapping("/page")
    public R<Page> getAll(Integer page, Integer pageSize, String name) {
        //分页构造器  设置当前页和每页查询条数
        Page<Dish> pageInfo = new Page<>(page, pageSize);
        Page<DishDto> dtoPage = new Page<>();
        //条件构造器  封装查询条件
        LambdaQueryWrapper<Dish> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StringUtils.isNotEmpty(name), Dish::getName, name);
        //按照更新时间降序排序
        wrapper.orderByDesc(Dish::getUpdateTime);
        //查询
        dishService.page(pageInfo, wrapper);
        //分类查询的数据
        List<Dish> dishes = pageInfo.getRecords();

        /**
         * * 拷贝对象,用的spring的BeanUtils工具类中copyProperties
         *   第一个参数是从哪个对象拷贝
         *   第二个参数是拷贝到哪个对象
         *   第三个参数是不需要拷贝的内容
         */

        BeanUtils.copyProperties(pageInfo, dtoPage, "dishes");

     /*   List<DishDto> dishDtoList = new ArrayList<>();
        //循环遍历dishes集合
        for (Dish dish : dishes) {
            //1.创建DishDto对象
            DishDto dishDto = new DishDto();
            //将dish对象拷贝到dishDto中
            BeanUtils.copyProperties(dish, dishDto);
            //2.查询分类表,根据菜品的id查询的菜品对应的categoryName
            //select * from where id=?     
            LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper<>();
            //category的id = dishDto/dish的categoryId
            queryWrapper.eq(Category::getId, dishDto.getCategoryId());
            //获取到对象
            Category category = categoryService.getOne(queryWrapper);
            //根据对象找到对应的categoryName
            String categoryName = category.getName();
            //将categoryName赋值给dishDto的categoryName
            dishDto.setCategoryName(categoryName);
            //将dishDto添加到dishDtoList
            dishDtoList.add(dishDto);
        }
        //设置Page<DishDto>的records
        dtoPage.setRecords(dishDtoList);
*/
        /** 1.将dishes列表转化为流的形式(用stream代替了for和forEach循环
         *   2.以map的数据格式获取所有dishes数据
         *   3.然后把所有的dishes放到一个collect集合中,然后转为list类型
         * */
        List<DishDto> list = dishes.stream().map((dish) -> {//dish  相当于  List<Dish> dishes
            //将dish拷贝到DishDto中
            DishDto dishDto = new DishDto();
            BeanUtils.copyProperties(dish, dishDto);
            //获取分类查询对象的id
            Long categoryId = dish.getCategoryId();
            //根据id获取到分类查询的对象
            Category category = categoryService.getById(categoryId);
            /**
             * 对category对象判空,
             * 不为空的情况下,
             * 获取对象的categoryName,
             * 并赋值给DishDto
             */
            if (category != null) {
                String categoryName = category.getName();
                dishDto.setCategoryName(categoryName);
            }
            return dishDto;
        }).collect(Collectors.toList());

        //将list 赋值给查询到 dishFlavorPage中的records
        dtoPage.setRecords(list);

        return R.success(dtoPage);
    }


    /**
     * 添加菜品
     *
     * @param dishDto
     * @return
     */
    @PostMapping
    public R save(@RequestBody DishDto dishDto) {
        //打印dishDto对象
        log.info("需要添加的dishDto:{}", dishDto);
        //向口味表添加菜品口味  调用saveFlavor将dishDto传入
        dishService.saveFlavor(dishDto);
        //同步redis中的菜品列表数据:删除缓存中的存储的菜品列表数据
        redisTemplate.delete("dish_" + dishDto.getCategoryId());
        //返回添加成功
        return R.success("新增菜品成功");
    }

    /**
     * 根据id查询菜品,用于回显
     *
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    public R getById(@PathVariable Long id) {
        //从dish表中查询菜品数据
        Dish dish = dishService.getById(id);
        log.info("查询到的菜品dish为:{}", dish);
        //查询菜品对应的口味
        //1.创建包含菜品口味的DishDto
        DishDto dishDto = new DishDto();
        //2.将dish对象拷贝到dishDto
        BeanUtils.copyProperties(dish, dishDto);
        //3.查询当前菜品的口味
        LambdaQueryWrapper<DishFlavor> wrapper = new LambdaQueryWrapper<>();
        //添加查询条件
        wrapper.eq(DishFlavor::getDishId, dish.getId());
        //获取当前菜品的口味
        List<DishFlavor> flavors = dishFlavorService.list(wrapper);
        //设置dishDto的口味赋值
        dishDto.setFlavors(flavors);
        return R.success(dishDto);
    }

    /**
     * 更新菜品
     * 请求url地址：/dish/1504708761831292929
     * 请求方式：GET
     * 请求参数：无
     * 响应结果【格式统一】：R 对象
     *
     * @param dishDto
     * @return
     */
    @PutMapping
    public R update(@RequestBody DishDto dishDto) {
        log.info("需要修改的dishDto:{}", dishDto);
        //调用service的修改方法,将dto对象传入
        dishService.updateFlavor(dishDto);
        //同步redis中的菜品列表数据:删除缓存中的存储的菜品列表数据
        Set keys = redisTemplate.keys("dish*");
        redisTemplate.delete(keys);
        return R.success("修改成功");
    }


    /**
     * 批量删除和单个删除
     *
     * @param ids
     * @return
     */
    @DeleteMapping
    public R delete(@RequestParam List<Long> ids) {//@RequestParam 前端传来的的参数时集合的话必须加@RequestParam注解
        log.info("需要删除的对象id;{}", ids);
        //根据菜品的id在菜品口味表中找到对应的口味进行删除
        for (Long id : ids) {
            LambdaQueryWrapper<DishFlavor> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(DishFlavor::getDishId, id);
            dishFlavorService.remove(wrapper);
        }
        //逻辑删除dish表中菜品
        dishService.removeByIds(ids);
        Set keys = redisTemplate.keys("dish*");
        redisTemplate.delete(keys);
        return R.success("删除成功");

    }

    /**
     * 修改菜品的状态
     * 请求url地址：/dish/status/1  ?ids=1504708761831292929,1504653856504483842,1413384757047271425
     * 请求方式：POST
     * 请求参数：?ids=1504708761831292929,1504653856504483842,1413384757047271425
     *
     * @param ids
     * @param status
     * @return
     */
    @PostMapping("/status/{status}")
    public R updateStatus(@RequestParam List<Long> ids, @PathVariable Integer status) {
        //循环遍历
        for (Long id : ids) {
            //根据id找到对象
            LambdaQueryWrapper<Dish> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Dish::getId, id);
            Dish dish = dishService.getOne(wrapper);
            //修改此对象的状态
            dish.setStatus(status);
            dishService.updateById(dish);
        }
        return R.success("操作成功");
    }

    /**
     * 新建套餐中的菜品
     * <p>
     * 根据id查询该分类下的所有菜品集合
     * 请求url地址：/dish/list    ?categoryId=139784426364237824
     * 请求方式：GET
     * 请求参数：?categoryId=1397844263642378242
     * 响应结果【格式统一】：R<List<Dish>> 对象
     *
     * @param dish
     * @return
     */

    /*public R<List<Dish>> list(Dish dish) {
        //条件构造器
        LambdaQueryWrapper<Dish> wrapper = new LambdaQueryWrapper<>();
        //在启售状态下的菜品
        wrapper.eq(dish.getCategoryId() != null, Dish::getCategoryId, dish.getCategoryId())
                .eq(Dish::getStatus, 1)
                .orderByAsc(Dish::getSort)
                .orderByDesc(Dish::getUpdateTime);
        List<Dish> list = dishService.list(wrapper);
        return R.success(list);
    }*/

    /**
     * > 请求url地址：/dish/list    ?categoryId=1397844303408574465&status=1
     * > DishController
     * 但是需要修改：修改方法的返回结果前：   R<List<Dish>>    菜品Dish的集合
     * 现在：   R<List<DishDto>>   返回的Dish集合中还需要有菜品的口味数据  DishDto【既包含菜品数据也包含菜品的口味数据】
     *
     * @param dish
     * @return
     */
    @GetMapping("/list")
    public R<List<DishDto>> list(Dish dish) {
        //从redis中获取指定分类下的菜品列表数据
        String dishRedisKey = "dish_" + dish.getCategoryId();
        List<DishDto> dishDtoList = (List<DishDto>) redisTemplate.opsForValue().get(dishRedisKey);
        //判断查询结果
        if (ObjectUtils.isNotEmpty(dishDtoList)) {
            return R.success(dishDtoList);
        }
        //条件构造器
        LambdaQueryWrapper<Dish> wrapper = new LambdaQueryWrapper<>();
        //在启售状态下的菜品
        wrapper.eq(dish.getCategoryId() != null, Dish::getCategoryId, dish.getCategoryId())
                .eq(Dish::getStatus, 1)
                .orderByAsc(Dish::getSort)
                .orderByDesc(Dish::getUpdateTime);
        List<Dish> dishes = dishService.list(wrapper);
        List<DishDto> dtoList = dishes.stream().map(item -> {
            //创建dto对象
            DishDto dishDto = new DishDto();
            //将菜[in信息拷贝到dto中
            BeanUtils.copyProperties(item, dishDto);
            //获取当前的分类id
            Long categoryId = item.getCategoryId();
            //根据id获取当前的对象
            Category category = categoryService.getById(categoryId);
            //对当前对象进行判空
            if (category != null) {
                //获取到当前的分类名称
                String categoryName = category.getName();
                //将分类名称赋值给dto
                dishDto.setCategoryName(categoryName);
            }
            //获取当前菜品的口味
            //1.获取当前菜品的id
            Long id = item.getId();
            //2.条件构造器 根据菜品id获取菜品口味
            LambdaQueryWrapper<DishFlavor> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(DishFlavor::getDishId, id);
            List<DishFlavor> flavors = dishFlavorService.list(queryWrapper);
            //3.给dto对象的口味赋值
            dishDto.setFlavors(flavors);
            return dishDto;
        }).collect(Collectors.toList());
        if (ObjectUtils.isNotEmpty(dtoList)) {
            redisTemplate.opsForValue().set(dishRedisKey, dtoList);
        }
        return R.success(dtoList);
    }
}
